
package model;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * Consumer process consists with data of the process and the table of its steps
 * and Actions.
 * 
 * @author Sydney Lin, Son Pham
 * @version 1.0
 */
public class Consumer extends Process
{
  /**
   * The read ok semaphore ID of this process.
   */
  private final int my_sem_readok_id;

  /**
   * The write ok semaphore ID of this process.
   */
  private final int my_sem_writeok_id;

  /**
   * Construct a Consumer object with the specified read_ok and write_ok
   * semaphores.
   * 
   * @param the_read_ok The read ok semaphore's ID.
   * @param the_write_ok The write ok semaphore's ID.
   * @param the_name The name
   */
  public Consumer(final int the_read_ok, final int the_write_ok,
                  final String the_name)
  {
    super(the_name);
    my_sem_readok_id = the_read_ok;
    my_sem_writeok_id = the_write_ok;

    super.setActionMap(generateActionMap(getNumAction() * 2));
    // super.setMaxStep();
  }

  /**
   * 
   * @param the_num_entries the number of steps of this process
   * @return The map of steps and actions corresponding the given
   *         the_num_entries
   */
  private Map<Integer, ProcessAction> generateActionMap(final int the_num_entries)
  {
    final Map<Integer, ProcessAction> the_action_map =
      new HashMap<Integer, ProcessAction>(the_num_entries);
  final Random random = new Random();
  int the_down_step;
  int the_up_step;
  int interval = getMaxStep() / (the_num_entries / 2);
  /*
   * Loop through the_num_entries and add elements to the table after checking
   * steps aren't repeated
   */
  for (int i = 0; i < the_num_entries / 2; i++)
  {      
    int lower_bound = i * interval;
    int upper_bound = (i + 1) * interval;
    do
    {
      the_down_step = random.nextInt(interval - 1) + lower_bound;
    }
    while (the_action_map.containsKey(the_down_step));

    the_action_map.put(the_down_step, ProcessAction.DOWN_ON_READ);

    do
    {
      the_up_step = random.nextInt(upper_bound - the_down_step + 1) + the_down_step;
    }
    while (the_action_map.containsKey(the_up_step));

    the_action_map.put(the_up_step, ProcessAction.UP_ON_WRITE);
  }
  return the_action_map;
  }

  /**
   * 
   * @return The read ok semaphore of this process.
   */
  public int getReadOkSemID()
  {
    return my_sem_readok_id;
  }

  /**
   * 
   * @return The write ok semaphore of this process.
   */
  public int getWriteOkSemID()
  {
    return my_sem_writeok_id;
  }
}
